#include "stdafx.h"
#include "Selector.h"
#include "ValidatorObj.h"
#include "ValidatorEach.h"
#include "SelectRule.h"
#include "EventArgs.h"
#include "CombatCard.h"
#include "CombatSessionImp.h"
#include "CardDef.h"

struct  SelectorDefReflectionRegister
{
	SelectorDefReflectionRegister()
	{
		REGISTER_REFLECTION_MEMBER(Selector,m_iID,INVALID_ID).Editor_SetAsPrimaryKey();
		REGISTER_REFLECTION_MEMBER(Selector,m_sDisplayName,std::string("DefaultName")).Editor_SetAsDisplayName();
		REGISTER_REFLECTION_MEMBER(Selector,m_eSelectRange,ESelectRange_FaceObj).Editor_SetAsEnumation<ESelectRange>();
		REGISTER_REFLECTION_MEMBER(Selector,m_iVOne,INVALID_ID).Editor_SetAsForeignKey(eDefGroup_Default,eDefaultDef_ValidatorObj);
		REGISTER_REFLECTION_MEMBER(Selector,m_iVEach,INVALID_ID).Editor_SetAsForeignKey(eDefGroup_Default,eDefaultDef_ValidatorEach);
		REGISTER_REFLECTION_MEMBER(Selector,m_iRule,INVALID_ID).Editor_SetAsForeignKey(eDefGroup_Default,eDefaultDef_SelectRules);
		REGISTER_REFLECTION_MEMBER(Selector,m_bAppendHero,ECombatSide_NULL).Editor_SetAsEnumation<ECombatSide>();

		GlobalClassManager::Instance().RegisterClass(Selector::s_GetReflection(),eDefaultDef_Selectors);
		GlobalDefManager::Instance().RegisterDefManger(&SelectorManager::Instance());

	}
}__selectordefreflectionregister;

void Selector::SelectTargets( EventArgBase& rEventArg,std::vector<CombatObj*>& vTargets ) const
{
		vTargets.clear();
		
		RangeSelect(rEventArg,vTargets);
		
		FilterObjects(vTargets);
		
		FilterEachObjects(rEventArg.m_pOwner,vTargets);

		SelectByRule(vTargets);

		if(m_bAppendHero!=ECombatSide_NULL &&vTargets.empty())
		{
			do 
			{
				if(rEventArg.m_pOwner->GetObjType()!=ECombatObj_Card) break;
				CombatCard *pOwner=(CombatCard *) rEventArg.m_pOwner;
				if(pOwner->GetStorage()!=ECardStorage_BattleField) break;
				uint8 iActID=pOwner->GetPlayerID();
				uint8 iOtherID=(iActID+1)%2;
				if(m_bAppendHero==ECombatSide_Other)
					vTargets.push_back(&rEventArg.m_pContext->GetHero(iOtherID));
				else
					vTargets.push_back(&rEventArg.m_pContext->GetHero(iActID));
			} while (false);			
		}
}

void Selector::RangeSelect(const EventArgBase& rEventArg, std::vector<CombatObj*>& vTargets ) const
{
	switch(m_eSelectRange)
	{
	case ESelectRange_FaceObj:
		{
			if(rEventArg.m_pOwner->GetObjType()!=ECombatObj_Card) break;
			CombatCard *pOwner=(CombatCard *) rEventArg.m_pOwner;
			if(pOwner->GetStorage()!=ECardStorage_BattleField) break;

			uint8 iActID=pOwner->GetPlayerID();
			uint8 iOtherID=(iActID+1)%2;

			BattleField& rBattleField=rEventArg.m_pContext->GetBattleField(iOtherID);
			CombatCard *pTarget=rBattleField.CardAt(pOwner->GetLocation());
			if(NULL!=pTarget)
			{
				vTargets.push_back(pTarget);
			}
		}break;
	case ESelectRange_FaceObjAndBeside:
		{
			if(rEventArg.m_pOwner->GetObjType()!=ECombatObj_Card) break;
			CombatCard *pOwner=(CombatCard *) rEventArg.m_pOwner;
			if(pOwner->GetStorage()!=ECardStorage_BattleField) break;

			uint8 iActID=pOwner->GetPlayerID();
			uint8 iOtherID=(iActID+1)%2;

			BattleField& rBattleField=rEventArg.m_pContext->GetBattleField(iOtherID);
			CombatCard *pTarget=rBattleField.CardAt(pOwner->GetLocation());
			if(NULL!=pTarget)
			{
				vTargets.push_back(pTarget);
				uint8 iLocation=pTarget->GetLocation();
				if(iLocation>0)
				{
					CombatCard * pCard=rBattleField.CardAt(iLocation-1);
					if(pCard) vTargets.push_back(pCard);
				}
				if(iLocation+1<BattleField::MAX_SIZE)
				{
					CombatCard * pCard=rBattleField.CardAt(iLocation+1);
					if(pCard) vTargets.push_back(pCard);
				}
			}

		}break;
	case  ESelectRange_FaceObjAndSameType:
		{
			if(rEventArg.m_pOwner->GetObjType()!=ECombatObj_Card) break;
			CombatCard *pOwner=(CombatCard *) rEventArg.m_pOwner;
			if(pOwner->GetStorage()!=ECardStorage_BattleField) break;

			uint8 iActID=pOwner->GetPlayerID();
			uint8 iOtherID=(iActID+1)%2;

			BattleField& rBattleField=rEventArg.m_pContext->GetBattleField(iOtherID);
			CombatCard *pTarget=rBattleField.CardAt(pOwner->GetLocation());
			if(NULL!=pTarget)
			{
				vTargets.push_back(pTarget);
				for(uint8 ii=0;ii<BattleField::MAX_SIZE;ii++)
				{
					CombatCard *pCard=rBattleField.CardAt(ii);
					if(pCard==NULL) continue;
					if(pCard==pTarget) continue;
					const CardDef * pTargetDef=pTarget->GetDef();
					const CardDef * pCardDef=pCard->GetDef();
					if(NULL==pTargetDef || NULL==pCardDef) continue;

					if(pCardDef->m_iTypeID ==pTargetDef->m_iTypeID) vTargets.push_back(pCard);
				}
			}

		}break;
	case ESelectRange_Other:
		{
			vTargets.push_back(rEventArg.m_pOther);
		}break;
	case ESelectRange_OtherAndBeside:
		{
			if(!rEventArg.m_pOther) break;
			if(rEventArg.m_pOther->GetObjType()!=ECombatObj_Card) break;
			CombatCard *pOther=(CombatCard *) rEventArg.m_pOther;
			if(pOther->GetStorage()!=ECardStorage_BattleField) break;
			BattleField& rBattleField=rEventArg.m_pContext->GetBattleField(pOther->GetPlayerID());

			vTargets.push_back(pOther);
			uint8 iLocation=pOther->GetLocation();
			if(iLocation>0)
			{
				CombatCard * pCard=rBattleField.CardAt(iLocation-1);
				if(pCard) vTargets.push_back(pCard);
			}
			if(iLocation+1<BattleField::MAX_SIZE)
			{
				CombatCard * pCard=rBattleField.CardAt(iLocation+1);
				if(pCard) vTargets.push_back(pCard);
			}

		}break;
	case  ESelectRange_OtherAndSameType:
		{
			if(!rEventArg.m_pOther) break;
			if(rEventArg.m_pOther->GetObjType()!=ECombatObj_Card) break;
			CombatCard *pOther=(CombatCard *) rEventArg.m_pOther;
			if(pOther->GetStorage()!=ECardStorage_BattleField) break;

			BattleField& rBattleField=rEventArg.m_pContext->GetBattleField(pOther->GetPlayerID());
			
			vTargets.push_back(pOther);
			for(uint8 ii=0;ii<BattleField::MAX_SIZE;ii++)
			{
				CombatCard *pCard=rBattleField.CardAt(ii);
				if(pCard==NULL) continue;
				if(pCard==pOther) continue;

				const CardDef * pOhterDef=pOther->GetDef();
				const CardDef * pCardDef=pCard->GetDef();
				if(NULL==pOhterDef || NULL==pCardDef) continue;

				if(pCardDef->m_iTypeID ==pOhterDef->m_iTypeID) vTargets.push_back(pCard);
			}
			

		}break;
	case ESelectRange_Self:
		{
			vTargets.push_back(rEventArg.m_pOwner);
		}break;
	case ESelectRange_SelfAndBeside:
		{
			if(rEventArg.m_pOwner->GetObjType()!=ECombatObj_Card) break;
			CombatCard *pOwner=(CombatCard *) rEventArg.m_pOwner;
			if(pOwner->GetStorage()!=ECardStorage_BattleField) break;
			BattleField& rBattleField=rEventArg.m_pContext->GetBattleField(pOwner->GetPlayerID());

			vTargets.push_back(pOwner);
			uint8 iLocation=pOwner->GetLocation();
			if(iLocation>0)
			{
				CombatCard * pCard=rBattleField.CardAt(iLocation-1);
				if(pCard) vTargets.push_back(pCard);
			}
			if(iLocation+1<BattleField::MAX_SIZE)
			{
				CombatCard * pCard=rBattleField.CardAt(iLocation+1);
				if(pCard) vTargets.push_back(pCard);
			}

		}break;
	case  ESelectRange_SelfAndSameType:
		{
			if(!rEventArg.m_pOwner) break;
			if(rEventArg.m_pOwner->GetObjType()!=ECombatObj_Card) break;
			CombatCard *pOwner=(CombatCard *) rEventArg.m_pOwner;
			if(pOwner->GetStorage()!=ECardStorage_BattleField) break;

			BattleField& rBattleField=rEventArg.m_pContext->GetBattleField(pOwner->GetPlayerID());
		
			vTargets.push_back(pOwner);
			for(uint8 ii=0;ii<BattleField::MAX_SIZE;ii++)
			{
				CombatCard *pCard=rBattleField.CardAt(ii);
				if(pCard==NULL) continue;
				if(pCard==pOwner) continue;

				const CardDef * pOwnerDef=pOwner->GetDef();
				const CardDef * pCardDef=pCard->GetDef();
				if(NULL==pOwnerDef || NULL==pCardDef) continue;

				if(pCardDef->m_iTypeID ==pOwnerDef->m_iTypeID) vTargets.push_back(pCard);
			}


		}break;
	case ESelectRange_HeroOur:
		{
			uint8 iActID=rEventArg.m_pOwner->GetPlayerID();
			vTargets.push_back(&rEventArg.m_pContext->GetHero(iActID));
		}break;
	case ESelectRange_HeroOther:
		{
			uint8 iActID=rEventArg.m_pOwner->GetPlayerID();
			uint8 iOtherID=(iActID+1)%2;
			vTargets.push_back(&rEventArg.m_pContext->GetHero(iOtherID));
		}break;
	case ESelectRange_HandOur:
		{
			uint8 iActID=rEventArg.m_pOwner->GetPlayerID();
			THandField& rField=rEventArg.m_pContext->GetHandField(iActID);
			for(uint32 ii=0;ii<rField.CardCount();ii++)
			{
				vTargets.push_back(rField.CardAt(ii));
			}

		}break;
	case ESelectRange_HandOther:
		{
			uint8 iActID=rEventArg.m_pOwner->GetPlayerID();
			uint8 iOtherID=(iActID+1)%2;
			THandField& rField=rEventArg.m_pContext->GetHandField(iOtherID);
			for(uint32 ii=0;ii<rField.CardCount();ii++)
			{
				vTargets.push_back(rField.CardAt(ii));
			}
			
		}break;
	case ESelectRange_BattleFieldOur:
		{
			uint8 iActID=rEventArg.m_pOwner->GetPlayerID();
			BattleField& rBattleField=rEventArg.m_pContext->GetBattleField(iActID);
			for(uint8 ii=0;ii<BattleField::MAX_SIZE;ii++)
			{
				CombatCard * pCard=rBattleField.CardAt(ii);
				if(pCard) vTargets.push_back(pCard);

			}
		}break;
	case ESelectRange_BattleFieldOther:
		{
			uint8 iActID=rEventArg.m_pOwner->GetPlayerID();
			uint8 iOtherID=(iActID+1)%2;
			BattleField& rBattleField=rEventArg.m_pContext->GetBattleField(iOtherID);
			for(uint8 ii=0;ii<BattleField::MAX_SIZE;ii++)
			{
				CombatCard * pCard=rBattleField.CardAt(ii);
				if(pCard) vTargets.push_back(pCard);

			}
		}break;
	case ESelectRange_TombOur:
		{
			uint8 iActID=rEventArg.m_pOwner->GetPlayerID();
			TombField& rField=rEventArg.m_pContext->GetTombField(iActID);
			for(uint32 ii=0;ii<rField.CardCount();ii++)
			{
				vTargets.push_back(rField.CardAt(ii));
			}
		}break;
	case ESelectRange_TombOther:
		{
			uint8 iActID=rEventArg.m_pOwner->GetPlayerID();
			uint8 iOtherID=(iActID+1)%2;
			TombField& rField=rEventArg.m_pContext->GetTombField(iOtherID);
			for(uint32 ii=0;ii<rField.CardCount();ii++)
			{
				vTargets.push_back(rField.CardAt(ii));
			}

		}break;
	case ESelectRange_AllBattleFiledCard:
		{
			for(uint8 kk=0;kk<2;kk++)
			{
				BattleField& rBattleField=rEventArg.m_pContext->GetBattleField(kk);
				for(uint8 ii=0;ii<BattleField::MAX_SIZE;ii++)
				{
					CombatCard * pCard=rBattleField.CardAt(ii);
					if(pCard) vTargets.push_back(pCard);
				}
			}
		}break;
	case ESelectRange_Src:
		{
			vTargets.push_back(rEventArg.m_pSrc);
		}break;
	case ESelectRange_CachedCard:
		{
			if(rEventArg.m_pCachedCard)
			{
				vTargets.push_back(rEventArg.m_pCachedCard);
			}
		}break;
	}
	
}

void Selector::FilterObjects( std::vector<CombatObj*>& vTargets ) const
{
	if(!m_pObjValidators) return;
	if(vTargets.empty()) return;
	std::vector<CombatObj*>  vTemp=vTargets;
	vTargets.clear();
	for(uint32 ii=0;ii<vTemp.size();ii++)
	{
		if(m_pObjValidators->Validate(vTemp[ii]))  vTargets.push_back(vTemp[ii]);
	}
}

void Selector::FilterEachObjects( CombatObj* pOwner,std::vector<CombatObj*>& vTargets ) const
{
	if(!m_pEachValidators) return;
	if(vTargets.empty()) return;
	std::vector<CombatObj*>  vTemp=vTargets;
	vTargets.clear();
	for(uint32 ii=0;ii<vTemp.size();ii++)
	{
		if(m_pEachValidators->Validate(pOwner,vTemp[ii]))  vTargets.push_back(vTemp[ii]);
	}
}

void Selector::SelectByRule( std::vector<CombatObj*>& vTargets ) const
{
	if(!m_pSelectRule) return;
	m_pSelectRule->ApplyRule(vTargets);
}

rewrite  void Selector::OnArchieveReaded()
{
	m_pObjValidators=ValidatorObjManager::Instance().LookupItem(m_iVOne);
	m_pEachValidators=ValidatorEachManager::Instance().LookupItem(m_iVEach);
	m_pSelectRule=SelectRuleManager::Instance().LookupItem(m_iRule);	
}
